#include <stdio.h>
#include <curl/curl.h>
#include <openssl/md5.h>
#include <stdlib.h>
#include <string.h>
#include <json-c/json.h>

struct buf_st{
    char *buffer;
    size_t size;
};


char *telId = "0";
char *plat = "squid";
char *sysplat = "speiyou";
char *skey = "com.xes.itempool";
char *uri = "http://icsinterface.speiyou.com/icsinterface/rest/curriculum/queryCacheAndQues";

int md5sum(char *string, int len, unsigned char *digest)
{
    MD5_CTX ctx;

    MD5_Init(&ctx);
    MD5_Update(&ctx, string, len);
    MD5_Final(digest, &ctx);

    return 0;
}

int get_json_data(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct buf_st *buf = (struct buf_st*)userp;

    buf->buffer = malloc(buf->size + realsize + 1);
    if(buf->buffer == NULL) {
        fprintf(stderr, "not enough buffer (malloc returned NULL)\n");
        return 0;
    }

    memcpy(&(buf->buffer[buf->size]), contents, realsize);
    buf->size += realsize;
    buf->buffer[buf->size] = 0;

    return realsize;
}

int json_parse_string(char *string, size_t length)
{
    json_object *root;
    json_object *result, *questions, *coursewares, *o;
    int i, len;

    root = json_tokener_parse(string);
    if (root == NULL) {
        fprintf(stderr, "parse json string error!\n");
        return -1;
    }

    printf("json.to_string()=%s\n", json_object_to_json_string(root));

    /* get root element */
    if (json_object_object_get_ex(root, "result", &result) == FALSE) {
        fprintf(stderr, "json obj 'result' not found!\n");
        return -1;
    }

    /* get questions element */
    if (json_object_object_get_ex(result, "questions", &questions) == FALSE) {
        fprintf(stderr, "json obj 'questions' not found!\n");
        return -1;
    }

    /* check the type of element */
    if (json_object_get_type(questions) != json_type_array) {
        fprintf(stderr, "json type 'questions' error!\n");
        return -1;
    }

    /* output result.questions */
    len = json_object_array_length(questions);
    fprintf(stderr, "result.questions[%d]=\n", len);
    for (i = 0; i < len; i++) {
        o = json_object_array_get_idx(questions, i);
        printf("\t[%d]=%s\n", i, json_object_to_json_string(o));
    }

    /* get coursewares element */
    if (json_object_object_get_ex(result, "coursewares", &coursewares) == FALSE) {
        fprintf(stderr, "json obj 'coursewares' not found!\n");
        return -1;
    }

    /* check the type of element */
    if (json_object_get_type(coursewares) != json_type_array) {
        fprintf(stderr, "json type 'coursewares' error!\n");
        return -1;
    }

    /* output result.coursewares */
    len = json_object_array_length(coursewares);
    fprintf(stderr, "result.coursewares[%d]=\n", len);
    for (i = 0; i < len; i++) {
        o = json_object_array_get_idx(coursewares, i);
        printf("\t[%d]=%s\n", i, json_object_to_json_string(o));
    }

    json_object_put(root);

    return 0;
}

int main(int argc, char *argv[])
{
    int i;
    char buffer[1024] = "";
    unsigned char digest[16];
    struct buf_st json_data;
    CURL *curl;
    CURLcode res;
    struct curl_slist *slist = NULL;

    /* show the sys/plat/tel infomation */
    fprintf(stderr, "plat=%s\n", plat);
    fprintf(stderr, "sys=%s\n", sysplat);
    fprintf(stderr, "tel=%s\n", telId);
    fprintf(stderr, "skey=%s\n", skey);

    /* make md5 */
    sprintf(buffer, "%s%s%s%s", telId, plat, sysplat, skey);
    fprintf(stderr, "md5sum('%s')\t", buffer);
    md5sum(buffer, strlen(buffer), digest);
    for (i = 0; i < 16; i++) {
        fprintf(stderr, "%02x", digest[i]);
    }
    fprintf(stderr, "\n");

    /* make url */
    sprintf(buffer, "%s?school=%s", uri, telId);
    fprintf(stderr, "url=%s\n", buffer);

    /* init curl */
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (curl == NULL) {
        printf("curl_easy_init() error");
        exit(2);
    }

    /* set url */
    curl_easy_setopt(curl, CURLOPT_URL, buffer);

    /* set http header */
    slist = curl_slist_append(slist, "User-Agent: Cache Squid python");
    slist = curl_slist_append(slist, "Accept: */*");
    slist = curl_slist_append(slist, "Content-type: text/plan");
    sprintf(buffer, "plat: %s", plat);
    slist = curl_slist_append(slist, buffer);
    sprintf(buffer, "sys: %s", sysplat);
    slist = curl_slist_append(slist, buffer);
    sprintf(buffer, "md5: %s", digest);
    slist = curl_slist_append(slist, buffer);
    sprintf(buffer, "key: ");
    slist = curl_slist_append(slist, buffer);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, get_json_data);
    json_data.buffer = NULL;
    json_data.size = 0;
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&json_data);

    /* run the curl */
    res = curl_easy_perform(curl);
    if (res != 0) {
        fprintf(stderr, "curl_easy_perform error");
        exit(1);
    }
    fprintf(stderr, "json_data=%s\n", json_data.buffer);

    /* parse the json string */
    json_parse_string(json_data.buffer, json_data.size);

    /* clean up */
    curl_slist_free_all(slist);
    curl_easy_cleanup(curl);
    curl_global_cleanup();

    exit(0);
}
